package com.example.statistics.ex

import android.Manifest
import android.app.Activity
import android.content.Context
import android.net.ConnectivityManager
import com.example.statistics.common.BaseActivity
import com.example.statistics.net.DataResult
import com.example.statistics.net.callback.DataDialogHttpCallback
import com.example.statistics.net.callback.DataHttpCallback
import com.example.statistics.net.callback.DownloadDialogHttpCallback
import com.example.statistics.utils.FileUtils
import com.example.statistics.utils.permissions.PermissionsCheck
import com.jhj.httplibrary.HttpCall
import com.jhj.httplibrary.adapt.CallAdapt
import com.jhj.httplibrary.model.HttpParams
import com.jhj.prompt.fragment.LoadingFragment
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import okhttp3.ConnectionPool
import okhttp3.OkHttpClient
import org.jetbrains.anko.toast
import java.io.File
import java.util.concurrent.TimeUnit

fun Context.isNetworkConnected(): Boolean {
    val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = manager.activeNetworkInfo
    if (networkInfo != null) {
        return networkInfo.isConnected
    }
    return false
}

data class HttpConfig(
        var isSuccessToast: Boolean = false,
        var isShowDialog: Boolean = false,
        var isFailureToast: Boolean = true,
        var isFailureFinish: Boolean = false,
        var httpParams: HttpParams = HttpParams(),
        var listParams: List<Pair<String, Any?>> = listOf(),
        var param: Pair<String, Any?>? = null
)

inline fun <reified T> Activity.httpGet(url: String, config: HttpConfig.() -> Unit = {}, crossinline result: (T?) -> Unit) {
    val httpConfig = HttpConfig()
    httpConfig.config()
    httpConfig.listParams.forEach {
        httpConfig.httpParams.put(it.first, it.second)
    }
    /* httpConfig.param?.let {
         httpConfig.httpParams.put(it.first, it.second)
     }*/
    HttpCall.get(url)
            .addParams(httpConfig.httpParams)
            .enqueue(object : DataHttpCallback<T>(this) {
                var dialog: LoadingFragment.Builder? = null
                override fun onStart() {
                    super.onStart()
                    if (httpConfig.isShowDialog)
                        dialog = loadingDialog { }
                }

                override val mIsOnSuccessToast: Boolean
                    get() = httpConfig.isSuccessToast

                override val mIsOnFailureToast: Boolean
                    get() = httpConfig.isFailureToast

                override val mIsOnFailureFinish: Boolean
                    get() = httpConfig.isFailureFinish

                override fun onSuccess(data: T?, resultType: ResultType) {
                    result(data)
                }

                override fun onFinish() {
                    super.onFinish()
                    if (dialog?.isShow() == true) {
                        dialog?.dismiss()
                    }

                }
            })
}

inline fun <reified T> Activity.httpPost(url: String, config: HttpConfig.() -> Unit = {}, crossinline result: (T?) -> Unit = {}) {
    val httpConfig = HttpConfig()
    httpConfig.config()
    httpConfig.listParams.forEach {
        httpConfig.httpParams.put(it.first, it.second)
    }
    HttpCall.post(url)
            .addParams(httpConfig.httpParams)
            .enqueue(object : DataHttpCallback<T>(this) {
                var dialog: LoadingFragment.Builder? = null
                override fun onStart() {
                    super.onStart()
                    if (httpConfig.isShowDialog)
                        dialog = loadingDialog("保存中...") { }
                }

                override val mIsOnSuccessToast: Boolean
                    get() = httpConfig.isSuccessToast

                override val mIsOnFailureToast: Boolean
                    get() = httpConfig.isFailureToast

                override val mIsOnFailureFinish: Boolean
                    get() = httpConfig.isFailureFinish

                override fun onSuccess(data: T?, resultType: ResultType) {
                    result(data)
                }

                override fun onFinish() {
                    super.onFinish()
                    if (dialog?.isShow() == true) {
                        dialog?.dismiss()
                    }

                }
            })
}


inline fun <reified T> Activity.post(url: String, isSuccessToast: Boolean = false, vararg pairs: Pair<String, Any?>, crossinline body: (T?) -> Unit) {
    HttpCall.post(url)
            .addParams(*pairs)
            .enqueue(object : DataHttpCallback<T>(this) {
                override val mIsOnSuccessToast: Boolean
                    get() = isSuccessToast

                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

inline fun <reified T> Activity.post(url: String, isSuccessToast: Boolean = false, params: HttpParams = HttpParams(), crossinline body: (T?) -> Unit) {
    HttpCall.post(url)
            .addParams(params)
            .enqueue(object : DataHttpCallback<T>(this) {
                override val mIsOnSuccessToast: Boolean
                    get() = isSuccessToast

                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

inline fun <reified T> Activity.postDialog(url: String, isSuccessToast: Boolean = false, vararg pairs: Pair<String, Any?>, crossinline body: (T?) -> Unit) {
    HttpCall.post(url)
            .addParams(*pairs)
            .enqueue(object : DataDialogHttpCallback<T>(this) {
                override val mIsOnSuccessToast: Boolean
                    get() = isSuccessToast

                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

inline fun <reified T> Activity.postDialog(url: String, isSuccessToast: Boolean = false, params: HttpParams = HttpParams(), crossinline body: (T?) -> Unit) {
    HttpCall.post(url)
            .addParams(params)
            .enqueue(object : DataDialogHttpCallback<T>(this) {
                override val mIsOnSuccessToast: Boolean
                    get() = isSuccessToast

                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

inline fun <reified T> Activity.get(url: String, vararg pairs: Pair<String, Any?>, crossinline body: (T?) -> Unit) {
    HttpCall.get(url)
            .addParams(*pairs)
            .enqueue(object : DataHttpCallback<T>(this) {
                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

inline fun <reified T> Activity.getAsync(url: String, vararg pairs: Pair<String, Any?>): T? {
    val clazz = this.javaClass.genericSuperclass

    val data = HttpCall.get(url)
            .addParams(*pairs)
            .adaptAsync(object : CallAdapt<T>() {})


    return data
}

inline fun <reified T> Activity.getSync(url: String, vararg pairs: Pair<String, Any?>): T? {
    val response = HttpCall.get(url)
            .addParams(*pairs)
            .adaptSync(object : CallAdapt<DataResult<T>>() {})
    return response?.data
}

inline fun <reified T> Activity.getDialog(url: String, vararg pairs: Pair<String, Any?>, crossinline body: (T?) -> Unit) {
    getDialog<T>(url, "正在加载中...", pairs = *pairs, body = body)
}

inline fun <reified T> Activity.getDialog(url: String, text: String = "正在加载中...", vararg pairs: Pair<String, Any?>, crossinline body: (T?) -> Unit) {

    HttpCall.get(url)
            .addParams(*pairs)
            .enqueue(object : DataDialogHttpCallback<T>(this, text) {
                override fun onSuccess(data: T?, resultType: ResultType) {
                    body(data)
                }
            })
}

fun BaseActivity.download(url: String, fileName: String, msg: String = "正在下载中...", body: (File) -> Unit = {}) {
    if (isNetworkConnected()) {
        PermissionsCheck.with(this)
                .requestPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .onPermissionsResult { _, _ ->
                    GlobalScope.launch(Dispatchers.Main) {
                        val file = File(FileUtils.getSDPath(FileUtils.FILE) + File.separator + fileName)
                        var fileSize = 0L
                        if (isNetworkConnected()) {
                            fileSize = url.fileSize()
                        }
                        if (file.exists()) {
                            if (file.length() == fileSize) {
                                body(file)
                            } else {
                                download(url, file, msg, body)
                            }
                        } else {
                            file.createNewFile()
                            download(url, file, msg, body)
                        }
                    }
                }

    } else {
        toast("网络连接失败！")
    }
}

private fun BaseActivity.download(url: String, file: File, msg: String, body: (File) -> Unit) {
    val client = OkHttpClient.Builder()
            .connectTimeout(120, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .connectionPool(ConnectionPool(32, 5, TimeUnit.SECONDS))
            .build()
    HttpCall.download(url)
            .setUseBaseUrl(false)
            //.setClient(client)
            .enqueue(object : DownloadDialogHttpCallback(this, file, msg) {
                override fun onSuccess(file: File) {
                    body(file)
                }

                override fun onFailure(msg: String) {
                    toast(msg)
                    if (file.exists()) {
                        file.delete()
                    }
                }
            })
}